package com.soft.admin.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.disk.DiskFileItem;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.soft.admin.common.ElementConst;
import com.soft.admin.dto.ComboDTO;
import com.soft.admin.dto.DownloadDTO;
import com.soft.admin.dto.DownloadDetailDTO;
import com.soft.admin.service.DownloadService;
import com.soft.dao.DownLoadDao;
import com.soft.model.Channel;
import com.soft.model.DownLoad;
import com.soft.model.DownLoadDetail;
import com.soft.model.User;
import com.soft.support.PageParam;
import com.soft.support.Pager;
import com.soft.util.DateUtil;
import com.soft.util.FileUtil;
import com.soft.util.JsonUtil;
import com.soft.util.RequestUtil;

@SuppressWarnings("unchecked")
@Component
public class DownloadServiceImpl implements DownloadService {
	
	private DownLoadDao downloadDao;
	
	@Autowired
	public void setDownloadDao(DownLoadDao downloadDao) {
		this.downloadDao = downloadDao;
	}

	@Transactional(readOnly = true)
	public String get(DownloadDTO params, PageParam page) {
		List<Criterion> values = new ArrayList<Criterion>();
		values.add(Restrictions.like("title", params.getTitle(), MatchMode.ANYWHERE));
		if (params.getChannel() != -1) {
			values.add(Restrictions.eq("channel.id", params.getChannel()));
		}
		if (params.getState() != -1) {
			values.add(Restrictions.eq("state", params.getState()));
		}
		Pager downLst = this.downloadDao.findForPager(DownLoad.class, 
				new Order[] { Order.desc("level"), Order.desc("releaseDate"), Order.desc("id") }, 
				page.getStart(), page.getLimit(), values);
		Pager pageModel = new Pager();
		pageModel.setTotal(downLst.getTotal());
		List<DownloadDTO> dtos = new ArrayList<DownloadDTO>();
		for (DownLoad down : (List<DownLoad>)downLst.getDatas()) {
			DownloadDTO dto = new DownloadDTO();
			BeanUtils.copyProperties(down, dto, new String[]{"channel", "user", "releaseDate", "updateDate"});
			dto.setChannel(down.getChannel().getId());
			dto.setUser(down.getUser().getId());
			dto.setReleaseDate(DateUtil.format(down.getReleaseDate()));
			dto.setUpdateDate(DateUtil.format(down.getUpdateDate()));
			dtos.add(dto);
		}
		pageModel.setDatas(dtos);
		return JsonUtil.toStringFromObject(pageModel);
	}
	
	@Transactional(readOnly = true)
	public String getFile(Integer id) {
		DownLoad download = (DownLoad)this.downloadDao.get(DownLoad.class, id);
		List<DownloadDetailDTO> files = new ArrayList<DownloadDetailDTO>();
		for (DownLoadDetail detail : download.getDetails()) {
			DownloadDetailDTO ddo = new DownloadDetailDTO();
			BeanUtils.copyProperties(detail, ddo);
			files.add(ddo);
		}
		return JsonUtil.toString(files);
	}
	
	@Transactional(readOnly = true)
	public String getChannel() {
		Channel chan = (Channel)this.downloadDao.findUniqueByProperty(Channel.class, "namespace", ElementConst.XZZXCONST);
		List<Channel> channels = this.downloadDao.findAll(Channel.class, null, Restrictions.eq("parent.id", chan.getId()));
		List<ComboDTO> dtos = new ArrayList<ComboDTO>();
		for (Channel channel : channels) {
			ComboDTO dto = new ComboDTO();
			dto.setId(channel.getId());
			dto.setStr(channel.getName());
			dtos.add(dto);
		}
		return JsonUtil.toString(dtos);
	}

	@Transactional(readOnly = true)
	public String getUser() {
		List<User> users = this.downloadDao.findAll(User.class, null);
		List<ComboDTO> dtos = new ArrayList<ComboDTO>();
		for (User user : users) {
			ComboDTO dto = new ComboDTO();
			dto.setId(user.getId());
			dto.setStr(user.getTruename());
			dtos.add(dto);
		}
		return JsonUtil.toString(dtos);
	}

	@Transactional
	public String addOrEdit(HttpServletRequest request, DownloadDTO params, String[] files) {
		DownLoad download = null;
		if (params.getId() == null) {
			download = new DownLoad();
			User user = (User)this.downloadDao.findUniqueByProperty(User.class, "username", RequestUtil.getUsername());
			download.setUser(user);
		} else {
			download = (DownLoad)this.downloadDao.get(DownLoad.class, params.getId());
		}
		download.setLevel(params.getLevel());
		download.setReleaseDate(DateUtil.format(params.getReleaseDate()));
		download.setUpdateDate(new Date());
		download.setState(params.getState());
		download.setTitle(params.getTitle());
		download.setTxt(params.getTxt());
		Channel channel = (Channel)this.downloadDao.get(Channel.class, params.getChannel());
		download.setChannel(channel);
		this.downloadDao.addOrEdit(download);
		Set<DownLoadDetail> details = download.getDetails();
		Map<String, DownLoadDetail> detMap = new HashMap<String, DownLoadDetail>();
		if (details != null && details.size() > 0) {
			for (DownLoadDetail detail : details) {
				detMap.put(detail.getUrl(), detail);
			}
		}
		if (files != null && files.length > 0) {
			for (String file : files) {
				String[] ffs = file.split(";");
				if (detMap.containsKey(ffs[1])) {
					DownLoadDetail detail = detMap.get(ffs[1]);
					if (!ffs[0].equals(detail.getTitle())) {
						detail.setTitle(ffs[0]);
						this.downloadDao.saveOrUpdate(ffs);
					}
					detMap.remove(ffs[1]);
				} else {
					DownLoadDetail detail = new DownLoadDetail();
					detail.setDownLoad(download);
					detail.setTitle(ffs[0]);
					detail.setUrl(ffs[1]);
					this.downloadDao.save(detail);
				}
			}
		}
		download.setDetails(null);
		String rootPath = request.getSession().getServletContext().getRealPath(ElementConst.SOURCESPATH);
		for (DownLoadDetail detail : detMap.values()) {
			FileUtil.delete(rootPath + File.separator + detail.getUrl());
			this.downloadDao.delete(detail);
		}
		return JsonUtil.toRes("保存成功！");
	}

	@Transactional
	public String remove(HttpServletRequest request, Integer id) {
		DownLoad download = (DownLoad)this.downloadDao.get(DownLoad.class, id);
		Set<DownLoadDetail> details = download.getDetails();
		String rootPath = request.getSession().getServletContext().getRealPath(ElementConst.SOURCESPATH);
		for (DownLoadDetail detail : details) {
			FileUtil.delete(rootPath + File.separator + detail.getUrl());
		}
		this.downloadDao.remove(download);
		return JsonUtil.toRes("删除成功！");
	}
	
	@Transactional
	public String upload(HttpServletRequest request) {
		MultipartHttpServletRequest mulrequest = (MultipartHttpServletRequest)request;
		CommonsMultipartFile file = (CommonsMultipartFile)mulrequest.getFile("fileupload");
		if (file.getSize() > 0) {
			DiskFileItem fileItem = (DiskFileItem) file.getFileItem();
			String fileStr = fileItem.getName().substring(fileItem.getName().lastIndexOf(".")).toLowerCase();
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss")+ fileStr;
			String rootPath = request.getSession().getServletContext().getRealPath(ElementConst.SOURCESPATH);
			String path = rootPath + File.separator + FileUtil.getPath(fileName) + File.separator;
			File targetDir = new File(path);
			if (!targetDir.exists()) targetDir.mkdirs();
			try {
				FileCopyUtils.copy(file.getBytes(), new File(path + fileName));
				return JsonUtil.toRes("上传成功！", FileUtil.getPath(fileName) + "/" + fileName);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return JsonUtil.toRes("上传失败！");
	}

}
